package com.tarena.csmall.seckill.security.config;

import com.tarena.csmall.seckill.security.filter.MyAuthenticationFilter;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * 当前项目所有http请求的认证逻辑
 * 基于这个类代码实现的
 */
@Configuration
@EnableWebSecurity
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
    //创建一个passport密码加密对象
    @Bean
    public PasswordEncoder passwordEncoder(){
        //和sso项目中的 密码解析器一致
        return new BCryptPasswordEncoder();
    }
    //认证配置方法
    @Bean
    public MyAuthenticationFilter myAuthenticationFilter(){
        return new MyAuthenticationFilter();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //如果有knife4j的页面 /resources swagger 资源
        String[] permitAll = {"*.html"};
        http.authorizeRequests().mvcMatchers(permitAll).permitAll();
        //1.所有请求都需要认证
        //2.关闭csrf验证 如果不关闭,所有post请求进入后都会验证一个csrf的字符串
        http.csrf().disable();
        //3.引入自定义过滤器 解析jwt,引入自定义 权限异常对象 认证异常对象
        http.authorizeRequests().anyRequest().authenticated();
        //必须在当前请求线程中 存在一个认证对象
        //没有这个认证对象,说明没有登录,返回自定义出口
        http.addFilterBefore(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
            @Override public void commence(HttpServletRequest request, HttpServletResponse response,
                AuthenticationException e) throws IOException, ServletException {
                //打印错误信息
                System.out.println("当前没有认证数据");
            }
        });
    }
}
